#ifndef WLAN_H
#define WLAN_H

#include <stdio.h>
#include <windows.h>

#define TRY \
    int line = 0xffffffff;

#define CATCH \
__catch__: \
    printf("error line: %d\n", line);

#define ASSERT(ret, exp) \
    if (ret != exp) { \
    line = __LINE__; \
    goto __catch__;}

#define CLIENT_VERSION_1 1
#define CLIENT_VERSION_2 2
#define WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES 0x00000001
#define WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES 0x00000002
#define DOT11_SSID_MAX_LENGTH 32
#define WLAN_MAX_PHY_TYPE_NUMBER 8

typedef ULONG WLAN_SIGNAL_QUALITY;
typedef ULONG WLAN_REASON_CODE;

typedef enum _WLAN_INTERFACE_STATE {
    wlan_interface_state_not_ready = 0,
    wlan_interface_state_connected = 1,
    wlan_interface_state_ad_hoc_network_formed = 2,
    wlan_interface_state_disconnecting = 3,
    wlan_interface_state_disconnected = 4,
    wlan_interface_state_associating = 5,
    wlan_interface_state_discovering = 6,
    wlan_interface_state_authenticating = 7
} WLAN_INTERFACE_STATE, *PWLAN_INTERFACE_STATE;

typedef enum _DOT11_PHY_TYPE {
    dot11_phy_type_unknown     = 0,
    dot11_phy_type_any         = 0,
    dot11_phy_type_fhss        = 1,
    dot11_phy_type_dsss        = 2,
    dot11_phy_type_irbaseband    = 3,
    dot11_phy_type_ofdm        = 4,
    dot11_phy_type_hrdsss        = 5,
    dot11_phy_type_erp         = 6,
    dot11_phy_type_ht            = 7,
    dot11_phy_type_vht         = 8,
    dot11_phy_type_IHV_start     = 0x80000000,
    dot11_phy_type_IHV_end     = 0xffffffff
} DOT11_PHY_TYPE, *PDOT11_PHY_TYPE;

typedef enum _DOT11_AUTH_ALGORITHM {
    DOT11_AUTH_ALGO_80211_OPEN        = 1,
    DOT11_AUTH_ALGO_80211_SHARED_KEY    = 2,
    DOT11_AUTH_ALGO_WPA                 = 3,
    DOT11_AUTH_ALGO_WPA_PSK             = 4,
    DOT11_AUTH_ALGO_WPA_NONE            = 5,
    DOT11_AUTH_ALGO_RSNA                = 6,
    DOT11_AUTH_ALGO_RSNA_PSK            = 7,
    DOT11_AUTH_ALGO_IHV_START         = 0x80000000,
    DOT11_AUTH_ALGO_IHV_END             = 0xffffffff
} DOT11_AUTH_ALGORITHM, *PDOT11_AUTH_ALGORITHM;

typedef enum _DOT11_CIPHER_ALGORITHM {
    DOT11_CIPHER_ALGO_NONE             = 0x00,
    DOT11_CIPHER_ALGO_WEP40            = 0x01,
    DOT11_CIPHER_ALGO_TKIP             = 0x02,
    DOT11_CIPHER_ALGO_CCMP             = 0x04,
    DOT11_CIPHER_ALGO_WEP104         = 0x05,
    DOT11_CIPHER_ALGO_WPA_USE_GROUP    = 0x100,
    DOT11_CIPHER_ALGO_RSN_USE_GROUP    = 0x100,
    DOT11_CIPHER_ALGO_WEP            = 0x101,
    DOT11_CIPHER_ALGO_IHV_START        = 0x80000000,
    DOT11_CIPHER_ALGO_IHV_END        = 0xffffffff
} DOT11_CIPHER_ALGORITHM, *PDOT11_CIPHER_ALGORITHM;

typedef enum _DOT11_BSS_TYPE {
    dot11_BSS_type_infrastructure    = 1,
    dot11_BSS_type_independent     = 2,
    dot11_BSS_type_any             = 3
} DOT11_BSS_TYPE, *PDOT11_BSS_TYPE;

typedef struct _DOT11_SSID {
    ULONG uSSIDLength;
    UCHAR ucSSID[DOT11_SSID_MAX_LENGTH];
} DOT11_SSID, *PDOT11_SSID;

typedef struct _WLAN_INTERFACE_INFO {
    GUID                 InterfaceGuid;
    WCHAR                strInterfaceDescription[256];
    WLAN_INTERFACE_STATE isState;
} WLAN_INTERFACE_INFO, *PWLAN_INTERFACE_INFO;

typedef struct _WLAN_INTERFACE_INFO_LIST {
    DWORD                 dwNumberOfItems;
    DWORD                 dwIndex;
    WLAN_INTERFACE_INFO InterfaceInfo[];
} WLAN_INTERFACE_INFO_LIST, *PWLAN_INTERFACE_INFO_LIST;

typedef struct _WLAN_AVAILABLE_NETWORK {
    WCHAR                    strProfileName[256];
    DOT11_SSID             dot11Ssid;
    DOT11_BSS_TYPE         dot11BssType;
    ULONG                    uNumberOfBssids;
    BOOL                     bNetworkConnectable;
    WLAN_REASON_CODE         wlanNotConnectableReason;
    ULONG                    uNumberOfPhyTypes;
    DOT11_PHY_TYPE         dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER];
    BOOL                     bMorePhyTypes;
    WLAN_SIGNAL_QUALITY    wlanSignalQuality;
    BOOL                     bSecurityEnabled;
    DOT11_AUTH_ALGORITHM     dot11DefaultAuthAlgorithm;
    DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
    DWORD                    dwFlags;
    DWORD                    dwReserved;
} WLAN_AVAILABLE_NETWORK, *PWLAN_AVAILABLE_NETWORK;

typedef struct _WLAN_AVAILABLE_NETWORK_LIST {
    DWORD                    dwNumberOfItems;
    DWORD                    dwIndex;
    WLAN_AVAILABLE_NETWORK Network[1];
} WLAN_AVAILABLE_NETWORK_LIST, *PWLAN_AVAILABLE_NETWORK_LIST;

typedef DWORD WINAPI (*fWlanOpenHandle)(
    DWORD dwClientVersion,
    PVOID pReserved,
    PDWORD pdwNegotiatedVersion,
    PHANDLE phClientHandle
);

typedef DWORD WINAPI (*fWlanEnumInterfaces)(
    HANDLE hClientHandle,
    PVOID pReserved,
    PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
);

typedef DWORD WINAPI (*fWlanGetAvailableNetworkList)(
    HANDLE hClientHandle,
    const GUID* pInterfaceGuid,
    DWORD dwFlags,
    PVOID pReserved,
    PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
);

typedef DWORD WINAPI (*fWlanCloseHandle)(
    HANDLE hClientHandle,
    PVOID pReserved
);

typedef VOID WINAPI (*fWlanFreeMemory)(
    PVOID pMemory
);

#endif /* WLAN_H */